package websocket

import (
	"encoding/json"
	"sync"
	"time"

	"github.com/gorilla/websocket"
	"gorm.io/gorm"
)

// WebSocketServer 简化的WebSocket服务器
type WebSocketServer struct {
	// 房间管理
	rooms   map[string]*Room
	roomsMu sync.RWMutex

	// 游戏房间管理
	gameRooms   map[string]*GameRoom
	gameRoomsMu sync.RWMutex

	// 房间列表客户端
	roomListClients map[string]*Client
	roomListMu      sync.RWMutex

	// 在线状态管理
	onlineStatusManager *OnlineStatusManager

	// 基础设施
	upgrader websocket.Upgrader
	db       *gorm.DB
}

// Room 统一的房间结构
type Room struct {
	ID          string
	Name        string
	Type        string // "chat" 或游戏类型
	CreatorID   string
	CreatorName string
	Clients     map[string]*Client
	UserNames   map[string]string
	JoinTimes   map[string]int64
	Ready       map[string]bool
	MaxUsers    int
	mu          sync.RWMutex

	// 游戏相关
	GameState      *GameState
	gameTicker     *time.Ticker
	gameLoopTicker *time.Ticker
	stopGame       chan struct{}
	gameMu         sync.RWMutex

	// 消息历史
	Messages []*Message

	// 自动销毁
	destroyTimer *time.Timer

	// 服务器引用
	server *WebSocketServer
}

// GameRoom 游戏房间（继承自Room）
type GameRoom struct {
	*Room
}

// Client WebSocket客户端
type Client struct {
	UserID     string
	UserName   string
	Conn       *websocket.Conn
	Send       chan []byte
	mu         sync.Mutex
	sendClosed bool
	server     *WebSocketServer
	// 添加连接状态管理
	isConnected bool
	closeOnce   sync.Once
}

// Close 安全关闭客户端连接
func (c *Client) Close() {
	c.closeOnce.Do(func() {
		c.mu.Lock()
		defer c.mu.Unlock()

		c.isConnected = false

		// 关闭发送通道
		if !c.sendClosed {
			close(c.Send)
			c.sendClosed = true
		}

		// 关闭WebSocket连接
		if c.Conn != nil {
			c.Conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
			c.Conn.Close()
			c.Conn = nil
		}
	})
}

// IsConnected 检查客户端是否已连接
func (c *Client) IsConnected() bool {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.isConnected && c.Conn != nil
}

// 消息类型常量
type MessageType int

const (
	MessageTypeJoin             MessageType = 1  // 加入房间
	MessageTypeLeave            MessageType = 2  // 离开房间
	MessageTypeText             MessageType = 3  // 文本消息
	MessageTypeReady            MessageType = 4  // 准备状态
	MessageTypeReadyChanged     MessageType = 5  // 准备状态变更
	MessageTypeGameOp           MessageType = 6  // 游戏操作
	MessageTypeGameState        MessageType = 7  // 游戏状态
	MessageTypeGameStart        MessageType = 8  // 游戏开始
	MessageTypeGameEnd          MessageType = 9  // 游戏结束
	MessageTypeRead             MessageType = 10 // 消息已读
	MessageTypeRoomListUpdate   MessageType = 11 // 房间列表更新
	MessageTypeUserListUpdate   MessageType = 12 // 用户列表更新
	MessageTypeRoomUserCount    MessageType = 13 // 房间人数更新
	MessageTypeUserStatusChange MessageType = 14 // 用户状态变更
	MessageTypeFriendsStatus    MessageType = 15 // 好友状态列表
	MessageTypeTravelNotice     MessageType = 16 // 虚拟旅行通知
	MessageTypeSystem           MessageType = 99 // 系统消息
)

// Message 统一的消息结构
type Message struct {
	ID       string                 `json:"id,omitempty"`
	Type     int                    `json:"type"`
	UserID   string                 `json:"user_id"`
	UserName string                 `json:"user_name"`
	Content  string                 `json:"content"`
	Time     int64                  `json:"time"`
	RoomID   string                 `json:"room_id,omitempty"`
	Data     map[string]interface{} `json:"data,omitempty"`
	ReadBy   map[string]bool        `json:"read_by,omitempty"`
}

// ToJSON 将消息转换为JSON字节数组
func (m *Message) ToJSON() []byte {
	jsonData, err := json.Marshal(m)
	if err != nil {
		return []byte(`{"type":99,"content":"消息序列化失败"}`)
	}
	return jsonData
}

// GameState 游戏状态
type GameState struct {
	Status    string                 `json:"status"` // waiting, playing, gameover
	StartTime int64                  `json:"start_time,omitempty"`
	EndTime   int64                  `json:"end_time,omitempty"`
	Snakes    map[string]*Snake      `json:"snakes,omitempty"`
	Foods     []SnakeSegment         `json:"foods,omitempty"`
	Scores    map[string]int         `json:"scores,omitempty"`
	Ready     map[string]bool        `json:"ready,omitempty"`
	Board     [][]int                `json:"board,omitempty"`
	Players   map[string]*PlayerInfo `json:"players,omitempty"`
}

// Snake 蛇游戏中的蛇
type Snake struct {
	Segments  []SnakeSegment `json:"segments"`
	Direction string         `json:"direction"`
	Alive     bool           `json:"alive"`
	Color     string         `json:"color,omitempty"`
}

// SnakeSegment 蛇的一段或食物的位置
type SnakeSegment struct {
	X int `json:"x"`
	Y int `json:"y"`
}

// PlayerInfo 玩家信息
type PlayerInfo struct {
	UserID   string `json:"user_id"`
	UserName string `json:"user_name"`
	Score    int    `json:"score,omitempty"`
	Ready    bool   `json:"ready,omitempty"`
	Color    string `json:"color,omitempty"`
	Alive    bool   `json:"alive,omitempty"`
}

// GameOp 玩家操作消息结构
type GameOp struct {
	Op       string `json:"op"`
	UserID   string `json:"user_id"`
	UserName string `json:"user_name,omitempty"`
	Dir      string `json:"dir,omitempty"`
	Ready    *bool  `json:"ready,omitempty"`
	X        int    `json:"x,omitempty"`
	Y        int    `json:"y,omitempty"`
}
